/*

*/

spell
	icon = 'spells.dmi'
	parent_type=/obj
	layer = MOB_LAYER+10

	name = ""

	var
		mob/owner

		list
			initial_components
			current_components
			component_count

		element = 0

		range
		power
		speed
		sustain

		average_tier

		hits_friendly

	LeftClick(player/clicker, loc, control, params)

		. = list()

		if(!clicker.target)
			for(var/mob/m in oview(clicker.client.view, clicker))
				clicker.target(m)
				break

		for(var/mob/m in view(clicker.range + range, clicker.target))
			. += m

		use(clicker, clicker.target, .)

	proc

		initialize(list/components, mob/caster)

			if(!components || !components.len) del src

			owner = caster

			initial_components = components
			current_components = copy_components()

			for(var/component/c in current_components)
				name += c.name
				if(c.element) element |= c.element

			if(!element)
				del src

			name = uppertext(copytext(name, 1, 2)) + copytext(name, 2)

			calc_tier()

			recalculate_count()

			recalculate_numbers()

			update_components()

			determine_icon()

		bit2color(bit)
			switch(bit)
				if(FIRE)	return "#ff0000"
				if(WIND)	return "#00ff00"
				if(DARK)	return "#000000"
				if(HOLY)	return "#cccccc"
				if(EARTH)	return "#330000"
				if(WATER)	return "#0000ff"
				if(HEALING)	return "#ff00ff"
				if(ELECTRIC)return "#ffff00"

		check_weak(mob/caster, mob/target, damage, bit)
			if((element & bit) && (target.resistance & bit))
				damage += round(damage*((target.resistance & ~bit)/BIT_MAX))
				if(damage > 0)
					target.take_damage(caster,damage, bit2color(bit))

		check_strong(mob/caster, mob/target, damage, bit)
			if((element & bit) && (target.resistance & bit))
				damage -= round(damage*((target.resistance & ~bit)/BIT_MAX))
				if(damage > 0)
					target.take_damage(caster,damage, bit2color(bit))

		modify_damage(mob/caster, mob/target, damage)
			if(target.resistance)
				/*
				TODO: refactor this to make it work more dynamically
				*/
				check_strong(caster, target, damage, FIRE)
				check_strong(caster, target, damage, WIND)
				check_strong(caster, target, damage, DARK)
				check_strong(caster, target, damage, HOLY)
				check_strong(caster, target, damage, EARTH)
				check_strong(caster, target, damage, WATER)
				check_strong(caster, target, damage, HEALING)
				check_strong(caster, target, damage, ELECTRIC)
				return damage

			if(target.weaknesses)
				check_weak(caster, target, damage, FIRE)
				check_weak(caster, target, damage, WIND)
				check_weak(caster, target, damage, DARK)
				check_weak(caster, target, damage, HOLY)
				check_weak(caster, target, damage, EARTH)
				check_weak(caster, target, damage, WATER)
				check_weak(caster, target, damage, HEALING)
				check_weak(caster, target, damage, ELECTRIC)
				return damage

			return 0

		cast(mob/caster, mob/initarget, mob/addtarget[])

			var/area/a = caster.loc.loc
			if(a.bits & NOMAGIC)
				caster << "An anti-magic field dissipates your magical energies!"
				return

			if(!caster.can_cast)return
			if(isplayer(caster))new/cast_bar(caster,(caster.speed_cast - speed ))
			for(var/atom/t in view(caster.range + range, initarget))
				if(isturf(t))
					t.overlays += icon(icon, icon_state)
					spawn(7)
						t.overlays = new/list()
				t.react(src, caster)

			for(var/mob/m in addtarget)
				if(m.client && hits_friendly || m == caster) continue
				if(!modify_damage(caster, m, power))
					var/root/r = get_root()
					m.take_damage(caster, power, bit2color(r.element))

			return 1

		get_root()
			for(var/component/c in current_components)
				if(isroot(c))
					return c

		calc_tier()

			average_tier = average_tier()

		average_tier()

			for(var/component/c in current_components)
				. += (c.tier * c.factor)
			. /= current_components.len
			.=min(max(1,round(.)), MAX_TIER)

		determine_icon()
			var/component/c = get_root()
			icon_state="[c.name][average_tier]"

		copy_components()

			. = new/list()
			for(var/component/c in initial_components)
				. += new c.type

		use(mob/caster, mob/target, mob/targets[])

			if(!cast(caster, target, targets)) return

			for(var/component/c in current_components)

				c.body = src

				c.use(caster, target)

			update_components()

		update_components()

			for(var/component/c in current_components)
				if(c.uses.get_current() <= 0 && c.uses.get_current()!=ROOT_NEGATIVE)

					if(c.child)
						current_components[current_components.Find(c)] = new c.child
					else
						current_components[current_components.Find(c)] = null

					calc_tier()
					recalculate_count()
					recalculate_numbers()
					name = recalculate_name()
					determine_icon()
					if(isplayer(owner))
						var/player/p = owner
						p.update_hotkeys()

		recalculate_count()

			component_count = new/list()
			for(var/component/c in current_components)
				component_count[c.name]++

		recalculate_name()

			for(var/component/c in current_components)
				if(c.uses.get_current() > 0 || isroot(c))
					. += c.name

		recalculate_numbers()
			range = 0
			power = 0
			speed = 0
			sustain = 0

			for(var/component/c in current_components)

				if(c.boost & RANGE)
					range += (c.boost & ~RANGE)

				if(c.boost & POWER)
					power += (c.boost & ~POWER)

				if(c.boost & SPEED)
					speed += (c.boost & ~SPEED)/10

				if(c.boost & SUSTAIN)
					sustain += (c.boost & ~SUSTAIN)

			for(var/component/c in current_components)
				if(!isroot(c))
					c.uses.set_max(c.uses.init() + sustain + owner.sustain)

		revitalize()

			current_components = copy_components()
			update_components()

		restore()

			for(var/component/c in current_components)
				c.restore()
			update_components()